/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package n64Controller;

import coisa.comm.Poller;
import coisa.debug.Cout;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import java.awt.AWTException;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * @author marcos
 */
public abstract class N64ControllerReader extends Poller.Reader {

    /**
     * Read this instructables' protocol:
     * http://www.instructables.com/id/Use-an-Arduino-with-an-N64-controller/
     * (And thanks a lot to this and the other references there! =] )
     */
    public static class Instructables extends N64ControllerReader {

        public Instructables() throws AWTException {
        }

        public Instructables(N64Controller controller) {
            super(controller);
        }

        @Override
        public void parseResponse(ArrayList<Byte> response) {
            if (!initiated) { // first message must likely to be malformed
                initiated = true;
                return;
            }
            char c;
            for (int i = 0; i < 16; ++i) {
                if (i == 8 || i == 9) {
                    continue;
                }
                c = (char) response.get(i).byteValue();
                if (c > '0' && c < '9') {
                    controller.press(buttons[i]);
                } else if (c == '0') {
                    controller.release(buttons[i]);
                }
            }
            String xy = "";
            for (int i = 17; i < response.size(); ++i) {
                c = (char) response.get(i).byteValue();
                xy = xy.concat("" + c);
            }
            String[] split = xy.split(" ");
            controller.move(new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1])));
        }
    }
    //
    //
    //
    public static int timeout = 1000;
    public static int delay = 25;
    public static int bufSize = 1000;
    public static byte separator = (byte) '\n';
    public static final N64Controller.Button[] buttons = N64Controller.Button.values();
    protected N64Controller controller;
    protected boolean initiated = false;
    private CommPort port;

    public N64ControllerReader(N64Controller controller) {
        setDelay(delay);
        this.controller = controller;
    }

    public N64ControllerReader() throws AWTException {
        this(new N64Controller());
    }

    public N64Controller getController() {
        return controller;
    }

    public void open(String portName) throws NoSuchPortException, PortInUseException, IOException {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        port = portIdentifier.open(this.getClass().toString(), timeout);
        init(port.getInputStream(), port.getOutputStream(), Arrays.asList(separator));
    }

    @Override
    protected void endPoll() {
        super.endPoll();
        port.close();
    }
}
